﻿module CommandsTests

open Microsoft.VisualStudio.TestTools.UnitTesting
open Commands

[<TestClass>]
type CommandsTests() = 
   
   [<TestMethod>]
   member public self.ReadCommand_FailsWhenCommandIsMissingDash() =
      let argv = [| "test" |]
      try
         let (taken, command) = ReadCommand(0, argv)

         Assert.Fail()
      with
         | _ as e -> Assert.IsTrue(e.Message.StartsWith("Missing '-'"))


   [<TestMethod>]
   member public self.ReadCommand_ReturnsATakenOfZeroPlusNoneWhenEmpty() =
      let argv = Array.empty<string>
      let actual = ReadCommand(0, argv)

      Assert.AreEqual(1,1)


   [<TestMethod>]
   member public self.ReadCommand_ReturnsATakenOfOnePlusKeyAndTrueWhenSwitchCommand() =
      let argv = [| "-test" |];
      let (taken, command) = ReadCommand(0, argv)

      Assert.AreEqual(1, taken)
      Assert.AreEqual("-test", command.Value.Name)
      Assert.AreEqual("true", command.Value.Value)


   [<TestMethod>]
   member public self.ReadCommand_FailsWhenNoValueDefinedForValueCommand() =
      let argv = [| "-test:" |];
      try
         let (taken, command) = ReadCommand(0, argv)

         Assert.Fail()
      with
         | _ as e -> Assert.IsTrue(e.Message.StartsWith("Missing value"))


   [<TestMethod>]
   member public self.ReadCommand_ReturnsATakenOfTwoPlusKeyAndValueWhenValueCommand() =
      let argv = [| "-test:"; "this" |];
      let (taken, command) = ReadCommand(0, argv)

      Assert.AreEqual(2, taken)
      Assert.AreEqual("-test:", command.Value.Name)
      Assert.AreEqual("this", command.Value.Value)


   [<TestMethod>]
   member public self.ReadCommands_ReturnsKeyAndValueForSwitchCommand() =
      let argv = [| "-test" |];
      let actual = ReadCommands(argv).[0]

      Assert.AreEqual("-test", actual.Name)
      Assert.AreEqual("true", actual.Value)
   

   [<TestMethod>]
   member public self.ReadCommands_ReturnsKeyAndValueForValueCommand() =
      let argv = [| "-test:"; "this" |];
      let actual = ReadCommands(argv).[0]

      Assert.AreEqual("-test:", actual.Name)
      Assert.AreEqual("this", actual.Value)      
       

   [<TestMethod>]
   member public self.ReadCommands_ReturnsKeyValuesForAllCommandLineArguments() =
      let argv = [| "-test:"; "this"; "-withoutfail" |];
      let actual = ReadCommands(argv) 

      Assert.AreEqual(2, actual.Length)

      let switch = actual.[0];
      
      Assert.AreEqual("-test:", switch.Name)
      Assert.AreEqual("this", switch.Value)      

      let value = actual.[1];
            
      Assert.AreEqual("-withoutfail", value.Name)
      Assert.AreEqual("true", value.Value)      
      

   [<TestMethod>]
   member public self.UpdateCommands_FailsWhenExistingIsNotUnique() =
      let argv = [| "-test:"; "this"; "-test:"; "that" |];
      let existing = ReadCommands(argv);
      try
         UpdateCommands(existing, Array.empty) |> ignore

         Assert.Fail()
      with
         | _ as e -> Assert.IsTrue(e.Message.StartsWith("Duplicate commands"))


   [<TestMethod>]
   member public self.UpdateCommands_FailsWhenUpdatesAreNotUnique() =
      let argv = [| "-test:"; "this"; "-test:"; "that" |];
      let updates = ReadCommands(argv);
      try
         UpdateCommands(Array.empty, updates) |> ignore

         Assert.Fail()
      with
         | _ as e -> Assert.IsTrue(e.Message.StartsWith("Duplicate commands"))


   [<TestMethod>]
   member public self.UpdateCommands_UpdatesExistingCommandsProperly() =      
      let existing = ReadCommands([| "-test1:"; "one"; "-test2:"; "fart" |])
      let updates = ReadCommands([| "-test2:"; "two" |])

      let actual = UpdateCommands(existing, updates)

      Assert.AreEqual("one", actual.[0].Value)
      Assert.AreEqual("two", actual.[1].Value)
      

